package net.siufung.security;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.boot.jwt.properties.JwtProperties;
import net.siufung.core.model.consts.Constants;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.Arrays;
import java.util.Map;

/**
 * @author 陈建峰
 * @since 2022/5/7 5:40 下午
 */
@SuppressWarnings("deprecation")
@Configuration
@AllArgsConstructor
@EnableConfigurationProperties({JwtProperties.class})
public class TokenEnhancerConfig {

    private final JwtProperties jwtProperties;

    @Bean
    public TokenEnhancerChain tokenEnhancer() {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(
                Arrays.asList(new TokenEnhancer(), accessTokenConverter()));
        return tokenEnhancerChain;
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(jwtProperties.getSigningKey());
        return converter;
    }

    @Slf4j
    static class TokenEnhancer
            implements org.springframework.security.oauth2.provider.token.TokenEnhancer {

        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            Map<String, Object> additionalInfo = Maps.newLinkedHashMap();
            if(authentication.isAuthenticated() && ObjectUtil.isNotNull(authentication.getUserAuthentication())){
                Object principal = authentication.getUserAuthentication().getPrincipal();
                JSONObject principalJson = (JSONObject) JSON.toJSON(principal);
                principalJson.remove("password");
                principalJson.remove("credentialsNonExpired");
                principalJson.remove("accountNonExpired");
                principalJson.remove("accountNonLocked");
                principalJson.remove("authorities");
                additionalInfo.put("success",Boolean.TRUE);
                additionalInfo.put(Constants.AUTH_CONTEXT_USER_KEY, principalJson);
            }
            DefaultOAuth2AccessToken defaultOauth2AccessToken = ((DefaultOAuth2AccessToken) accessToken);
            defaultOauth2AccessToken.setAdditionalInformation(additionalInfo);
            defaultOauth2AccessToken.setTokenType(authentication.getOAuth2Request().getGrantType());
            defaultOauth2AccessToken.setScope(null);
            return defaultOauth2AccessToken;
        }
    }

}
